#include "tthreadpool.h"
using namespace std;
namespace tlib
{
TThreadPool::TThreadPool() :
    m_bRunning(false)
{

}

TThreadPool::~TThreadPool()
{
  if (m_bRunning)
    Stop();
}

void TThreadPool::runInThread()
{
  while (m_bRunning)
  {
    TTask task = Take();
    task();
  }
}

void TThreadPool::Start(int numThreads)
{
  m_bRunning = true;
  for (int i = 0; i < numThreads; i++)
  {
    TThread* thread = new TThread;
    thread->Run(bind(&TThreadPool::runInThread, this));
    m_threads.push_back(thread);
  }
}

void TThreadPool::Stop()
{
  {
    TAutoLock lock(&m_mutex);
    m_bRunning = false;
    m_bNotEmpty.NotifyAll();
  }
  for (vector<TThread*>::iterator it = m_threads.begin(); it != m_threads.end(); it++)
  {
    (*it)->Join();
  }
}

void TThreadPool::Run(TTask tk)
{
  TAutoLock lock(&m_mutex);
  m_tasks.push_back(tk);
  m_bNotEmpty.Notify();
}

TTask TThreadPool::Take()
{
  TAutoLock lock(&m_mutex);
  while (m_tasks.empty() && m_bRunning)
  {
    m_bNotEmpty.Wait(&m_mutex);
  }
  TTask task;
  if (!m_tasks.empty())
  {
    task = m_tasks.front();
    m_tasks.pop_front();
  }
  return task;
}
}
